home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!ukma!rutgers!mit-eddie!uw-beaver!tektronix!tekgen!tekred!games-request
- From: games-request@tekred.TEK.COM
- Newsgroups: comp.sources.games
- Subject: v01i066: roll - automatic dice roller
- Message-ID: <1356@tekred.TEK.COM>
- Date: 29 Jun 87 23:47:13 GMT
- Expires: 29 Jul 87 23:45:54 GMT
- Sender: billr@tekred.TEK.COM
- Lines: 393
- Approved: billr@tekred.TEK.COM
-
- Submitted by: Bruce Holloway <drivax!holloway@ames.arpa>
- Comp.sources.games: Volume 1, Issue 66
- Archive-name: roll
-
- [I haven't tried this, so you're on your own. -br]
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: README Makefile roll.c
- # Wrapped by billr@tekred on Mon Jun 29 16:37:32 1987
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f README -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"README\"
- else
- echo shar: Extracting \"README\" \(985 characters\)
- sed "s/^X//" >README <<'END_OF_README'
- XThe Ultimate Dice Roller! Should be transportable to most systems that
- Xcan run 'C' and have the standard library.
- X
- XThis dice roller is random, even if the random number generator isn't very
- Xrandom.
- X
- XUsage: (options included in braces):
- X
- Xroll {numrep@}{{bestroll,}numroll x}{{bestdice,}numdice d}{sides}
- X
- Xnumrep [1] = number of times to repeat the rolling sequence.
- Xbestroll [numroll] = print the best "bestroll" rolls.
- Xnumroll [1] = number of rolls to do.
- Xbestdice [numdice] = use the "bestdice" highest rolling dice.
- Xnumdice [1] = number of dice to use per roll.
- Xsides [100] = number of sides on the dice.
- X
- XExamples:
- X roll
- X d100 = 65
- X roll 6
- X d6 = 3
- X roll 4d10
- X 4d10 = 11
- X roll 5,10d8
- X 5,10d8 = 28
- X roll 6x3d6
- X 6x3d6 = 17 12 11 11 10 6
- X roll 6x3,4d6
- X 6x3,4d6 = 18 15 10 10 7 6
- X roll 5,10x4d4
- X 5,10x4d4 = 14 13 12 12 10
- X roll 3@6,10x3,4d6
- X 6,10x3,4d6 = 17 17 15 15 14 14
- X 6,10x3,4d6 = 18 15 15 15 14 14
- X 6,10x3,4d6 = 16 14 13 13 11 11
- X
- END_OF_README
- if test 985 -ne `wc -c <README`; then
- echo shar: \"README\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f Makefile -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"Makefile\"
- else
- echo shar: Extracting \"Makefile\" \(229 characters\)
- sed "s/^X//" >Makefile <<'END_OF_Makefile'
- X# Makefile for ROLL
- X#
- X# Comment out the BSD line if you're on System V
- X# Comment out the SYSV line if you're using Berkely Unix.
- X
- X# SYSTEM = -DSYSV
- XSYSTEM = -DBSD
- X
- XCFLAGS = -O $(SYSTEM)
- X
- Xroll: roll.c
- X cc -o roll $(CFLAGS) roll.c
- END_OF_Makefile
- if test 229 -ne `wc -c <Makefile`; then
- echo shar: \"Makefile\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f roll.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"roll.c\"
- else
- echo shar: Extracting \"roll.c\" \(7305 characters\)
- sed "s/^X//" >roll.c <<'END_OF_roll.c'
- X/*****************************************************************************
- X* ROLL - Rolls dice - lots of them - and really randomly.
- X*
- X*
- X* Usage: (options included in braces):
- X*
- X* roll {numrep@}{{bestroll,}numroll x}{{bestdice,}numdice d}{sides}
- X*
- X* numrep [1] = number of times to repeat the rolling sequence.
- X* bestroll [numroll] = print the best "bestroll" rolls.
- X* numroll [1] = number of rolls to do.
- X* bestdice [numdice] = use the "bestdice" highest rolling dice.
- X* numdice [1] = number of dice to use per roll.
- X* sides [100] = number of sides on the dice.
- X*
- X* Examples:
- X* roll
- X* d100 = 65
- X* roll 6
- X* d6 = 3
- X* roll 4d10
- X* 4d10 = 11
- X* roll 5,10d8
- X* 5,10d8 = 28
- X* roll 6x3d6
- X* 6x3d6 = 17 12 11 11 10 6
- X* roll 6x3,4d6
- X* 6x3,4d6 = 18 15 10 10 7 6
- X* roll 5,10x4d4
- X* 5,10x4d4 = 14 13 12 12 10
- X* roll 3@6,10x3,4d6
- X* 6,10x3,4d6 = 17 17 15 15 14 14
- X* 6,10x3,4d6 = 18 15 15 15 14 14
- X* 6,10x3,4d6 = 16 14 13 13 11 11
- X******************************************************************************/
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X
- X#define NUMREDUX 5
- X
- X#ifdef SYSV
- X#define index strchr
- X#define rindex strrchr
- X#define srandom srand
- X#define random rand
- X#endif
- X
- Xextern char *index(), *rindex();
- Xextern char *malloc();
- Xextern void free();
- X
- Xint numroll = 1, bestroll = 1; /* Number of rolls to roll and keep */
- Xint numdice = 1, bestdice = 1; /* Number of dice to roll and keep */
- Xint sides = 100; /* Number of sides on each die */
- X
- Xint *ar_rolls; /* Array of rolls */
- Xint *ar_dice; /* Array of dice */
- Xint *ar_side; /* Array of side data */
- X
- Xchar *show(); /* Routine to format output */
- X
- Xchar iline[80]; /* To parse the roll */
- Xchar aroll[80]; /* When rolls are repeated */
- X
- Xmain(acnt,avar)
- Xint acnt;
- Xchar *avar[];
- X{
- X int i, j, k, val;
- X char *s, *s1;
- X
- X/* if(acnt < 2){
- X printf("usage: roll {numroll x }{numdice d }{numsides}\n");
- X printf("\tExample: roll 100 ; roll 3d8 ; roll 6x3d8\n");
- X return;
- X }
- X*/
- X srandom(time(0L)); /* Randomize */
- X
- X if(acnt <= 1) /* Default: Roll 1d100 */
- X roll("");
- X else
- X for(i=0; ++i < acnt;){ /* For each argument */
- X s = avar[i];
- X if(s1 = index(s,'@')){ /* Repeat the roll? */
- X *s1 = 0;
- X j = atoi(s); /* Get repetition */
- X if(j < 1){
- X printf("roll: Repetition count must be greater than zero.\n");
- X return;
- X }
- X s = s1+1; /* Advance pointer past it */
- X }
- X else j = 1; /* Default: Only one time. */
- X strcpy(aroll,s); /* Save it. */
- X while(j--){
- X strcpy(s,aroll);
- X roll(s); /* Do the roll */
- X }
- X }
- X}
- X
- Xroll(inline)
- Xchar *inline;
- X{
- X int i, j, k, val, r;
- X char *s, *s1;
- X
- X numroll = bestroll = bestdice = numdice = 1; /* Set defaults. */
- X sides = 100;
- X
- X for(s=inline; *s; ++s) /* Convert to lower case */
- X if(isupper(*s))
- X *s = tolower(*s);
- X
- X s = inline;
- X if(s1 = index(s,'x')){ /* Get number of rolls */
- X *s1 = 0;
- X parse(s,&numroll,&bestroll);
- X s = s1+1;
- X }
- X if(s1 = index(s,'d')){ /* Get number of dice */
- X *s1 = 0;
- X parse(s,&numdice,&bestdice);
- X s = s1+1;
- X }
- X if(*s) sides = atoi(s); /* get number of sides */
- X
- X if(error()) return; /* Check sanity */
- X
- X if(numroll > 1) printf("%sx",show(iline,bestroll,numroll));
- X if(numdice > 1) printf("%s",show(iline,bestdice,numdice));
- X printf("d%d = ",sides);
- X fflush(stdout); /* Echo the command */
- X
- X/* Allocate the arrays - one to keep all the rolls, one to keep each roll
- X by the die roll, and one to make sure the dice are rolled RANDOMLY.
- X*/
- X ar_rolls = (int *)malloc(sizeof(int) * numroll);
- X ar_dice = (int *)malloc(sizeof(int) * numdice);
- X ar_side = (int *)malloc(sizeof(int) * NUMREDUX * sides);
- X
- X/* Get out if we couldn't allocate the arrays */
- X
- X if(!ar_rolls || !ar_dice || !ar_side){
- X printf("*** Out of memory ***\n");
- X if(ar_rolls) free(ar_rolls);
- X if(ar_dice) free(ar_dice);
- X if(ar_side) free(ar_side);
- X return;
- X }
- X
- X/* Make an array filled with the possible side values. Several times. So
- X that even if the random number generator isn't completely random, it
- X has a chance to produce random values when indexing into the array.
- X*/
- X for(i=j=0; i<NUMREDUX; ++i)
- X for(k=0; k++ < sides; ++j)
- X *(ar_side+j) = k;
- X
- X/* Randomize the array - necessary to catch cyclic random number generators. */
- X
- X for(i=0; i < NUMREDUX * sides; ++i){
- X r = random();
- X if(r < 0) r = -r;
- X r %= NUMREDUX * sides;
- X j = *(ar_side+i);
- X *(ar_side+i) = *(ar_side+r);
- X *(ar_side+r) = j;
- X }
- X
- X for(i = 0; i<numroll; ++i){ /* For each roll */
- X for(j=0; j<numdice; ++j){ /* For each die */
- X r = random(); /* Roll the die */
- X if(r < 0) r = -r;
- X *(ar_dice+j) = *(ar_side + (r % (sides * NUMREDUX)));
- X }
- X if(bestdice < numdice) sort(ar_dice,numdice); /* Get the best 'n' */
- X for(j=val=0; j<bestdice; ++j) /* Sum them to get the roll */
- X val += *(ar_dice+j);
- X *(ar_rolls+i) = val;
- X }
- X sort(ar_rolls,numroll); /* Sort the rolls */
- X for(i=0; i<bestroll; ++i) /* And print out the best 'n' */
- X printf("%d ",*(ar_rolls+i));
- X printf("\n");
- X
- X free(ar_rolls); /* Free all the arrays */
- X free(ar_dice);
- X free(ar_side);
- X}
- X
- X/*****************************************************************************
- X* PARSE
- X*
- X* Figure out strings that look like "ddd" and "ddd,ddd", and fill in
- X* the values nicely. Handle defaults, too.
- X******************************************************************************/
- X
- Xparse(s,n,b)
- Xchar *s;
- Xint *n, *b;
- X{
- X char *s1;
- X
- X if(s1 = index(s,',')){
- X *s1 = 0;
- X *b = atoi(s);
- X *n = atoi(s1+1);
- X }
- X else *b = *n = atoi(s);
- X}
- X
- X/*****************************************************************************
- X* SORT
- X*
- X* Bubble sort (yech) an array.
- X******************************************************************************/
- X
- Xsort(a,n)
- Xint a[], n;
- X{
- X int changed, i, t;
- X
- X if(n <= 1) return;
- X
- X for(changed=1; changed;){
- X changed = 0;
- X for(i=0; i<n-1; ++i){
- X if(a[i] < a[i+1]){
- X changed = 1;
- X t = a[i]; a[i] = a[i+1]; a[i+1] = t;
- X }
- X }
- X }
- X}
- X
- X/*****************************************************************************
- X* ERROR
- X*
- X* Scan and report any errors.
- X******************************************************************************/
- X
- Xerror(){
- X int iserr=0;
- X
- X if(numroll <= 0){
- X fprintf(stderr,"roll: Number of rolls must be greater than zero.\n");
- X ++iserr;
- X }
- X
- X if(bestroll < 1 || bestroll > numroll){
- X fprintf(stderr,"roll: Number of rolls to keep must be greater than zero,\n");
- X fprintf(stderr," less than the total number of rolls.\n");
- X ++iserr;
- X }
- X
- X if(numdice <= 0){
- X fprintf(stderr,"roll: Number of dice to roll must be greater than zero.\n");
- X ++iserr;
- X }
- X
- X if(bestdice < 1 || bestdice > numdice){
- X fprintf(stderr,"roll: Number of dice to keep must be greater than zero,\n");
- X fprintf(stderr," less than the number of dice.\n");
- X ++iserr;
- X }
- X
- X if(sides <= 1){
- X fprintf(stderr,"roll: Dice must have at least two sides.\n");
- X ++iserr;
- X }
- X
- X return(iserr);
- X}
- X
- X/*****************************************************************************
- X* SHOW
- X*
- X* Format some output.
- X******************************************************************************/
- X
- Xchar *show(s,b,n)
- Xchar *s;
- Xint b, n;
- X{
- X if(b == n)
- X sprintf(s,"%d",n);
- X else
- X sprintf(s,"%d,%d",b,n);
- X return(s);
- X}
- END_OF_roll.c
- if test 7305 -ne `wc -c <roll.c`; then
- echo shar: \"roll.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of shell archive.
- exit 0
-